import simpy

from .common import Event

DELETE = 0
INSERT = 1

class FibUpdate(object):
    def __init__(self, table, utype, match, priority, action):
        self.table = table
        self.utype = utype
        self.match = match
        self.priority = priority
        self.action = action

class FibUpdateMessage(Event):
    def __init__(self, timestamp, device_id, epoch, batch_id, updates):
        Event.__init__(self, timestamp, device_id)
        self.epoch = epoch
        self.batch_id = batch_id
        self.updates = updates

class FibRecorder(object):
    def __init__(self, config):
        from pathlib import Path
        import datetime

        path = config['path'].get(str)
        Path(path).mkdir(parents=True, exist_ok=True)

        self.path = path
        now = datetime.datetime.now()
        self.filename = '{1}/fib-{0:%m}-{0:%d}-{0:%H}-{0:%M}.csv'.format(now, self.path)
        self.fout = open(self.filename, 'w')

        self.env = None
        self.channel = None

    def configure(self, env):
        self.env = env

        self.channel = simpy.Store(self.env, capacity=simpy.core.Infinity)

        self.write_header()

        self.env.process(self.record_fib_updates())

    def write_header(self):
        headers = [
            'epoch', 'timestamp', 'dev',
            'table', 'batch_id', 'utype',
            'match', 'priority', 'action'
        ]
        self.fout.write(','.join(headers) + '\n')
        self.fout.flush()

    def record_fib_updates(self):
        while True:
            req = yield self.channel.get()

            if isinstance(req, FibUpdateMessage):
                epoch, ts, dev = str(req.epoch), req.timestamp, req.sender
                bid = req.batch_id
                for u in req.updates:
                    table = u.table
                    utype = '+' if u.utype == INSERT else '-'
                    match = ' '.join(['%s=%s' % (k, u.match[k])
                                      for k in u.match])
                    fmt = '%s,%d,%s,%d,%d,%s,%s,%d,%s\n'
                    s = fmt % (epoch, ts, dev, table, bid, utype,
                               match, u.priority, u.action)
                    self.fout.write(s)
                self.fout.flush()

    def close(self):
        self.fout.close()
